home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
dirutl
/
tree.arc
/
TREE.ASM
next >
Wrap
Assembly Source File
|
1986-08-27
|
14KB
|
535 lines
; tree.asm g.r.green
; program to draw directory tree of the default drive
; running msdos.
;
; changes made to accomodate for the IBM line drawing set
; Hans ZURFCC::Zangger Aug 86 {Baum == german for 'tree'
;
; TREE.ASM Copyright (C) by Gordon R. Green
; 9-May-1985 All Rights Reserved. Released For Any
; use without cost exceeding the cost of handling
; and reproduction, as long this heading is
; included with all or any part used of this
; program and credit given to Gordon R. Green.
;
; Gordon R. Green
; 7 Juniper St.
; Hudson, N.H. 03051
;
;
; Installation Instructions:
; masm tree
; link tree ; ignore lack of stack err msg!!!
; exe2bin tree.exe tree.com
; del tree.exe
;
; Invocation:
; TREE ; takes no arguments
;**************************************************************
; Macro definitions
; DISPLAY STRING
display macro string
mov dx,offset string
mov ah,9
int doscall
endm
; SET_DTA
set_dta macro buffer
mov dx,offset buffer
mov ah,1AH
int doscall
endm
; SEARCH_FIRST
search_first macro fcb
mov dx,offset fcb
mov ah,11H
int doscall
endm
;
FSCROLL EQU 6 ;BIOS function = scroll
FLOCATE EQU 2 ;BIOS function = locate
COLOR EQU 7 ;attribute, white on black background
ALL EQU 0 ;indicates entire screen on scroll
HOR EQU 196
VER EQU 179
COR EQU 192
LFIN EQU 195
TFIN EQU 194
BFIN EQU 192
FACE EQU 1
;
BIOSCAL MACRO FUNCTION
MOV AH,FUNCTION ;specify function desired
INT 10H ;call BIOS for desired function
ENDM
;
SCROLL MACRO POS1,POS2,ATTRIBUTE,ROWS
;;coordinates to be presented in row,col format as a single number, as:
;;row * 256 + col
;;
;;POS1 =upper left coordinate
;;POS2 =lower right coordinate
;;ATTRIBUTE =color descriptor of fill character
;;ROWS =how many rows to be scrolled (0=do entire screen)
MOV CX,POS1 ;upper left corner
MOV DX,POS2 ;botton right corner
MOV BH,ATTRIBUTE ;pass how to color fill
MOV AL,ROWS ;do entire window
BIOSCAL FSCROLL ;request scroll function from bios
ENDM
;
LOCATE MACRO ROW,COL
MOV DH,ROW ;move cursor to this row
MOV DL,COL ;and to this col in this screen number
MOV BH,0
BIOSCAL FLOCATE ;move cursor
ENDM
;
; End of macros
;**************************************************************
;**************************
;*** ***
;*** EQU Statements ***
;*** ***
;**************************
max_level equ 14
doscall equ 21H
; dos calls
type_chr equ 2
find_file equ 4EH
find_nxt_file equ 4FH
; ASCII characters
CR equ 0DH
LF equ 0AH
H_TAB equ 9
;**************************
;*** ***
;*** Main Program ***
;*** ***
;**************************
;***********************************************************
prognam segment ;define code segment
org 100H
assume cs:prognam, ds:prognam, ss:prognam
start:
push ds ; set up return to DOS
call crlf
xor ax,ax ; clear ax
push ax
call init ; init tables, save current directory,
; switch to root
; read disk name and display it
set_dta buffer
search_first fcb ; look for disk name
cmp al,0FFH ; found?
jne name_fnd ; if yes
; mov al," " ; else fill in blank name
;display hig_vid
display no_label ; else say No Label
jmp nolabel
mov di,offset buffer+8
mov cx,11
repz stosb
name_fnd:
mov al,"$" ; insert string terminator
mov buffer[19],al
;display hig_vid
;display spaces1
display buffer[8] ; display name in reverse video
nolabel:
;display reg_vid
display link ; draw lines down to main tree
mov unused,3 ; force proper positioning later
; read root directory into memory and sort it
mov di,offset buf ; pntr to filename storage
mov begin_dir,di
call get_file_names ; get filenames for this level
mov bx,level
mov begin_dir[bx+2],di ; mark start of next level
mov num_dir[bx],ax ; save # of directories at this level
cmp ax,0 ; any sub-diretories?
je no_sub_dirs ; if none in root, then no tree
main_loop:
mov bx,level ; all dirs done at this level?
mov ax,cur_dir[bx]
cmp ax,num_dir[bx]
jne more_dirs ; if not
cmp bx,0 ; are we at top level?
jne up ; if no
abort: jmp quit ; if yes
more_dirs:
call dn_level ; go down one level
mov bx,level ; init di with where to store filenames
mov di,begin_dir[bx]
call get_file_names
mov bx,level ; save pntr for next level
mov begin_dir[bx+2],di
mov num_dir[bx],ax ; save # dirs at this level
mov cur_dir[bx],0 ; set cur_dir=0 for this level
cmp ax,0 ; any dirs?
jne more_dirs ; if yes, go dn another level
call crlf
mov unused,-1
up:
call up_level ; else go up a level
mov bx,level ; bump cnt of cur_dir
inc cur_dir[bx]
jmp main_loop ; and loop back
quit:
call crlf
mov ah,3BH ; restore original directory
mov dx,offset old_dir
int doscall
ret ; exit to dos
no_sub_dirs:
display no_subdirs
jmp quit
;**********************************
;*** ***
;*** Support Routines ***
;*** ***
;**********************************
;**************************************************************
; initialize a bunch of things
; on entry ax = 0
init:
; init tables (begin_dir, num_dir, cur_dir)
mov di,offset begin_dir ; (ax = 0)
mov cx,max_level * 3
repz stosw
mov level,ax ; (ax = 0)
; init default file spec at 5CH
mov al,"?" ; fill with wildcards
mov di,byte ptr 5DH ; default fcb+1
mov cx,11
repz stosb
; save current directory name
mov ah,47H ; get current directory name
mov si,offset old_dir+1 ; and put here
mov dl,0 ; from present drive
int doscall
; change to root_directory
mov ah,3BH ; change current directory
mov dx,offset root_dir ; to root-directory
int doscall
scroll 0,24*256+79,color,all ; scroll row=24, col=79 (zero relative)
locate 0,0 ;Cursor to top left at (0,0)
locate 0,65
display sign_on
locate 0,0
ret ; escape sequence
;**************************************************************
; move down a directory level
dn_level:
; move to new directory
mov bx,level
mov si,begin_dir[bx] ; where names start for this level
mov ax,cur_dir[bx] ; cur_dir
mov cx,11
mul cl ; times size = offset
add ax,si ; ax points to next name
mov si,ax ; move to si
mov di,offset dn_dir + 2
mov cx,8 ; ready to move 8 chars
repz movsb
call show_name ; display the directory name
mov ah,3BH ; change current directory
mov dx,offset dn_dir
cmp level,0
jne dn_lv
inc dx
dn_lv:
int doscall ;### error chk?
inc level ; adjust level count
inc level ; by 2
ret
;**************************************************************
; show directory name
show_name:
cmp unused,-1 ; new line?
jne shnm0 ; if not
call do_indents
mov unused,0
shnm0: mov cx,unused ; any unused?
cmp cx,0 ; if not
je shnm2
shnm1: mov dl, HOR ; else pad with hor lines
mov ah,2
int doscall
loop shnm1
shnm2: mov bx,level
mov end_pad, LFIN ; init end_pad to left "T"
cmp cur_dir [bx],0 ; determine end_pad value
jne shnm3
mov end_pad, TFIN ; if 1st, top "T"
shnm3: mov ax,cur_dir [bx]
inc ax
cmp ax,num_dir [bx]
jne shnm4
mov end_pad, BFIN ; if last, lower left corner
shnm4: dec ax
cmp ax,0
jne shnm5
cmp num_dir[bx],1
jg shnm5
mov end_pad, HOR ; if 1st & last, horizontal line
shnm5: mov dl,end_pad ; output end_pad
mov ah,2
int doscall
;display spaces1
;display hig_vid ; switch to reverse video
mov bx,offset dn_dir + 2 ; output name
mov dl,[bx] ; first character
mov ah,2
int doscall
inc bx
mov cx,7 ; 7 more characters in filename
shnm6: mov dl,[bx] ; all but first char in lower case
cmp dl,0
je shnm8 ; if nul
cmp dl,"A"
jl shnm7
cmp dl,"Z"
; jg shnm7
; or dl," "
shnm7: mov ah,2 ; finally output char
int doscall
inc bx
loop shnm6 ; loop for all chars
shnm8: mov unused,cx
;display spaces1
;display reg_vid ; back to normal video
ret
;**************************************************************
; handle the indents at beginning of line
do_indents:
mov bx,0 ; "level" for this routine
do_ind1:
display spaces8 ; output leading spaces8
cmp bx,level ; done if present level
je do_ind3
mov dl," " ; else output space
mov ax,cur_dir [bx]
inc ax
cmp ax,num_dir [bx]
je do_ind2
;display spaces1
mov dl, VER ; or vertical bar
do_ind2:
mov ah,2
int doscall
do_ind3:
inc bx ; bump local index
inc bx
cmp bx,level ; see if we are done
jle do_ind1 ; if not
ret
;**************************************************************
; move up a directory level
up_level:
mov ah,3BH ; change current directory
mov dx,offset up_dir ; up a level
int doscall ;### error chk?
dec level ; adjust level count
dec level ; by 2
ret
;**************************************************************
; get list of files that match
; entry - di = addr of place to put data
; return - di = addr of next data loc
; ax = # files found (stored in tmp_cnt during routine)
get_file_names:
mov tmp_loc,di
mov tmp_cnt,0 ; init file cntr for this routine
push di
set_dta fb_reserve ; set data transfer area
mov al,0 ; clear fb_pname area
mov di,offset fb_pname
mov cx,11
repz stosb
pop di
mov ah,find_file ; find match file
mov dx,5DH ; point at default fcb+1
mov cx,010H ; attributes to look for
int doscall
jnc sav_nam ; if we found something
mov ax,0 ; else
ret ; return with cnt=0
sav_nam:
cmp fb_attr,10H ; directory?
jne no_save ; if not
cmp fb_pname, '.' ; named "."?
je no_save ; if yes
mov si,offset fb_pname ; else save filename
mov cx,11
repz movsb
inc tmp_cnt ; bump file cnt
no_save:
push di
mov al,0 ; clear fb_pname area
mov di,offset fb_pname
mov cx,13
repz stosb
pop di
mov ah,find_nxt_file ; find nxt file match
int doscall
cmp al,18 ; any file?
jnz sav_nam ; yes
call sort
mov ax,tmp_cnt ; no, return ax = tmp_cnt
ret
;**************************************************************
; sort list of files
; entry - di = nxt data loc
; tmp_loc = start of data to sort
; tmp_cnt = how many to sort
; return - di = nxt data loc
; data area is sorted
sort: push di
cmp tmp_cnt,1 ; more than one?
jnz sort_start ; yes
jmp sort_done ; no - only one
sort_start:
mov bx,tmp_loc
mov dl,0
mov dh,1
sort1: mov si,bx
mov di,si
add di,11
mov cx,8
repz cmpsb
jle sort3
mov cx,11
mov dl,1
mov si,bx
mov di,si
add di,11
sort2: mov al,[si]
xchg [di],al
mov [si],al
inc si
inc di
loop sort2
sort3: add bx,11
inc dh
mov al,dh ;### expand to 16 bit cnt
xor ah,ah
cmp ax,tmp_cnt
jl sort1
cmp dl,1
jz sort_start
sort_done:
pop di
ret
;**************************************************************
; type cr, lf
crlf:
display crlf_msg
ret
;**********************************
;*** ***
;*** Storage Allocation ***
;*** ***
;**********************************
;**************************************************************
crlf_msg db CR, LF, "$"
root_dir db "\",0
up_dir db "..",0 ; go up a directory level
dn_dir db ".\", 16 dup (?)
old_dir db "\", 64 dup (?) ; saves original directory
no_label db "No DiskLabel$"
no_subdirs db " No SubDirs$"
sign_on db "Baum V1.2 ", FACE, "$"
end_pad db (?) ; graphic joining character
link db CR, LF, " ", COR, "$"; link from disk name
spaces8 db " $" ; 8 spaces
spaces1 db " $" ; 1 space
tmp_cnt dw (?) ; temporary counter
tmp_loc dw (?) ; tmp location storage
unused dw -1 ; # chars not used in field
; 'level' is current directory level (0 = root), and is used as index into
; begin_dir, num_dir, and cur_dir arrays. begin_dir array stores addresses
; in buf where the data for each level begins. num_dir array stores the
; number of directories at each level. cur_dir array stores the number
; of the directory being processed at each level. Whenever we move up
; one level, the data for all lower levels is obsolete and the pointers
; are now invalid and the corresponding area in 'buf' may be re-used.
level dw (?) ; current level ( 0 - ((n-1)*2) )
begin_dir dw max_level dup (?) ; index within BUF where data starts
num_dir dw max_level dup (?) ; # dirs at this level
cur_dir dw max_level dup (?) ; # of dir being proc. at this level
; CAUTION!!! be careful when making modifications.
; The buffers from here on are used at different times and are overlapping.
; 'fcb' overlaps 'buffer', and 'buffer' overlaps 'fb_*' and 'buf'.
fcb db 0FFH, 0,0,0,0,0,8, 0, "???????????"
buffer db (?)
fb_reserve db 21 dup (?) ; data returned about file
fb_attr db ?
fb_time dw ?
fb_date dw ?
fb_size_lo dw ?
fb_size_hi dw ?
fb_pname db 13 dup (?)
buf: db (?) ; buffer area from here to stack
; stores sorted directories for
; all levels
prognam ends ;end of code segment
end start ;end assembly